package loja.services;

import java.math.BigDecimal;
import java.util.List;

import loja.dao.DAOFactory;
import loja.dao.pessoa.cliente.ClienteDAO;
import loja.model.conta.operacao.Operacao;
import loja.model.pessoa.Contato;
import loja.model.pessoa.Endereco;
import loja.model.pessoa.cliente.Cliente;
import loja.model.venda.Venda;
import loja.services.factory.ServiceFactory;

public class ClienteService {

	private ClienteDAO clienteDao;
	private ServiceFactory serviceFactory;

	public ClienteService(ServiceFactory serviceFactory, DAOFactory daoFactory) {
		this.clienteDao = daoFactory.getClienteDAO();
		this.serviceFactory = serviceFactory;
	}

	public void incluirCliente(Cliente cliente) {
		clienteDao.incluir(cliente);
	}

	public void removerClientePorId(Long id) {
		clienteDao.remover(clienteDao.consultarPorId(id));

	}

	public List<Cliente> listarClientes() {
		return clienteDao.listar();
	}

	public Cliente consultarClientePorNome(String nome) {
		return clienteDao.consultarPorNome(nome);
	}

	public List<Cliente> listarClientePorNome(String nome) {
		return clienteDao.listarPorNome(nome);
	}

	public Cliente consultarClientePorId(Long id) {
		return clienteDao.consultarPorId(id);
	}

	public void alterarContatoCliente(Long id, Contato contato) {
		Cliente cliente = clienteDao.consultarPorId(id);
		cliente.setContato(contato);
		clienteDao.alterar(cliente);
	}

	public void alterarEnderecoCliente(Long id, Endereco endereco) {
		Cliente cliente = clienteDao.consultarPorId(id);
		cliente.setEndereco(endereco);
		clienteDao.alterar(cliente);

	}

	public void alterarLimiteCliente(Long id, double limite) {
		Cliente cliente = clienteDao.consultarPorId(id);
		cliente.setLimite(limite);
		clienteDao.alterar(cliente);

	}

	public void alterarDadosCliente(Long id, Contato contato,
			Endereco endereco, double limite) {

		Cliente cliente = clienteDao.consultarPorId(id);
		cliente.setContato(contato);
		cliente.setEndereco(endereco);
		cliente.setLimite(limite);
		clienteDao.alterar(cliente);
	}

	public void incluirPagamentoCliente(Long idCliente, BigDecimal valorRecebido) {

		Cliente cliente = this.clienteDao.consultarPorId(idCliente);
		this.serviceFactory.getTransacaoService().incluirCredito(
				cliente.getTitular(), "PAGAMENTO", valorRecebido);
		this.serviceFactory.getTransacaoService().incluirCredito(null,
				"RECEBIDO CLIENTE " + cliente.getIdPessoa(), valorRecebido);

		atualizarValorVendasAReceberDeCliente(valorRecebido, cliente);

	}

	public List<Operacao> listarOperacoesContaCliente(Long id) {
		return this.serviceFactory.getTransacaoService().listarOperacoesConta(
				clienteDao.consultarPorId(id).getTitular());
	}

	public void atualizarValorVendasAReceberDeCliente(Cliente cliente) {
		atualizarValorVendasAReceberDeCliente(BigDecimal.ZERO, cliente);
	}

	private void atualizarValorVendasAReceberDeCliente(BigDecimal valorRecebido,
			Cliente cliente) {

		List<Venda> vendas = this.serviceFactory.getVendaService()
				.listarVendasAReceberDeCliente(cliente);

		BigDecimal saldoConta = serviceFactory.getTransacaoService()
				.getSaldoConta(cliente.getTitular());

		if (saldoConta.compareTo(BigDecimal.ZERO) > 0)
			valorRecebido = valorRecebido.add(saldoConta);

		for (Venda venda : vendas) {

			if (valorRecebido.compareTo(BigDecimal.ZERO) == 0)
				break;

			BigDecimal valorVenda = this.serviceFactory.getVendaService()
					.valorVenda(venda);
			BigDecimal valorPago = venda.getValor();

			if (valorVenda.compareTo(valorPago) == 0)
				continue;

			BigDecimal valorDiferenca = valorVenda.subtract(valorPago);

			if (valorDiferenca.compareTo(valorRecebido) >= 0) {
				valorPago = valorPago.add(valorRecebido);
				this.serviceFactory.getVendaService().alterarValorVenda(
						venda.getIdVenda(), valorPago);
				valorRecebido = BigDecimal.ZERO;

			} else {
				this.serviceFactory.getVendaService().alterarValorVenda(
						venda.getIdVenda(), valorVenda);
				valorRecebido = valorRecebido.subtract(valorDiferenca);
			}
		}
	}
}
